import fs from 'node:fs/promises'
import * as ejs from './ejs'
// const debug = require('debug')('koa-ejs')
/**
 * default render options
 */
const defaultSettings = {
  cache: true,
  layout: 'layout',
  viewExt: '.ejs',
  locals: {},
  compileDebug: false,
  debug: false,
  autoRender: true,
  async: false
}

/**
 * set app.context.render
 *
 * usage:
 * ```
 * await ctx.render('user', {name: 'dead_horse'});
 * ```
 * https://github.com/queckezz/koa-views/blob/master/src/index.js
 */
export function ejsView(path, options = defaultSettings) {
  if(!path) {
    throw new Error('path required')
  }
  options = {
    ...defaultSettings,
    ...options,
    root: path.resolve(process.cwd(), path)
  }
  const cache = {}

  // override `ejs` node_module `resolveInclude` function
  ejs.resolveInclude = function(name, filename, isDir) {
    if(!path.extname(name)) name += options.viewExt
    return ejs.resolveInclude(name, filename, isDir)
  }

  return function views(ctx, next) {

    /**
     * generate html with view name and options
     *
     * @param {String} view
     * @param {Object} options
     * @return {Promise<String>} html
     */
    async function renderEjs(view, model) {
      const viewPath = path.join(options.root, view + options.viewExt)
      // from cache
      if(options.cache && cache[viewPath]) return cache[viewPath](options.scope, model)

      const tpl = await fs.readFile(viewPath, 'utf8')

      const fn = ejs.compile(tpl, {
        filename: viewPath,
        compileDebug: options.debug && options.compileDebug,
        debug: options.debug,
        delimiter: options.delimiter,
        cache: options.cache,
        async: options.async,
        outputFunctionName: options.outputFunctionName
      })

      if(options.cache) {
        cache[viewPath] = fn
      }

      return fn.call(options.scope, model)
    }

    async function render(relPath, locals = {}) {
      const ctx = this
      const model = Object.assign({
        layout: options.layout,
        autoRender: options.autoRender,
        ...options.locals
      }, ctx.state, locals)
      let html = await renderEjs(relPath, model)

      // layout.ejs 应该有一段内容为 <%- body %>
      if(model.layout) {
        model.body = html
        html = await renderEjs(model.layout, model)
      }

      if(model.autoRender) {
        ctx.type = 'text/html'
        ctx.body = html
      }

      return html
    }

    if(!ctx.render) {
      ctx.render = render
    }

    return next()
  }
}
